package com.classes;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.classes.accessflags.AccessFlagsEnum;
import com.classes.field.FiledAccessFlagEnum;
import com.classes.method.MethodAccessFlagEnum;

public class CMN {
    public static Map<String, int[]> classAccessFlagMap = new HashMap<>();
    public static Map<String, int[]> fieldAccessFlagMap = new HashMap<>();
    public static Map<String, int[]> methodAccessFlagMap = new HashMap<>();

    public static void init() {
        //类访问标识
        AccessFlagsEnum[] values = AccessFlagsEnum.values();
        int[] array = new int[values.length];
        for (int i = 0; i < array.length; i++) {
            array[i] = values[i].getFlag();
        }

        for (int i = 1; i < values.length; i++) {
            ArrayList<int[]> cmn = cmn(array, i);
            for (int[] ar : cmn) {
                int result = 0;
                for (int n : ar) {
                    result += n;
                }
                classAccessFlagMap.put(result + "", ar);
            }
        }


        //字段访问标识
        FiledAccessFlagEnum[] fieldValues = FiledAccessFlagEnum.values();
        int[] fieldArray = new int[fieldValues.length];
        for (int i = 0; i < fieldArray.length; i++) {
            fieldArray[i] = fieldValues[i].getFlag();
        }

        for (int i = 1; i < fieldValues.length; i++) {
            ArrayList<int[]> cmn = cmn(fieldArray, i);
            for (int[] ar : cmn) {
                int result = 0;
                for (int n : ar) {
                    result += n;
                }
                methodAccessFlagMap.put(result + "", ar);
            }
        }


        //方法访问标识
        MethodAccessFlagEnum[] methodValues = MethodAccessFlagEnum.values();
        int[] methodArray = new int[methodValues.length];
        for (int i = 0; i < methodArray.length; i++) {
            methodArray[i] = methodValues[i].getFlag();
        }

        for (int i = 1; i < methodValues.length; i++) {
            ArrayList<int[]> cmn = cmn(methodArray, i);
            for (int[] ar : cmn) {
                int result = 0;
                for (int n : ar) {
                    result += n;
                }
                fieldAccessFlagMap.put(result + "", ar);
            }
        }


    }


    public static ArrayList<int[]> cmn(int[] source, int m) {
        // 声明一个存放所有分组的集合
        ArrayList<int[]> result = new ArrayList<int[]>();

        // 如果每个组合的长度是1，那么就是原数组长度的单个内容，
        if (m == 1) {
            for (int i = 0; i < source.length; i++) {
                result.add(new int[]{source[i]});
            }
            // 如果组合的长度是原数组的长度，那么只有一个分组就是原数组
        } else if (source.length == m) {
            result.add(source);

        } else {
            int[] psource = new int[source.length - 1]; // 临时数组，为参数数组长度减1
            for (int i = 0; i < psource.length; i++) {
                psource[i] = source[i];
            }
            result = cmn(psource, m);
            ArrayList<int[]> tmp = cmn(psource, m - 1);
            for (int i = 0; i < tmp.size(); i++) {
                int[] rs = new int[m];
                for (int j = 0; j < m - 1; j++) {
                    rs[j] = tmp.get(i)[j];
                }
                rs[m - 1] = source[source.length - 1];
                result.add(rs);
            }
        }
        return result;
    }

    // 求一个数组的任意组合
    public static ArrayList<int[]> RandomC(int[] source) {
        ArrayList<int[]> result = new ArrayList<int[]>();
        if (source.length == 1) {
            result.add(source);
        } else {
            int[] psource = new int[source.length - 1];
            for (int i = 0; i < psource.length; i++) {
                psource[i] = source[i];
            }
            result = RandomC(psource);
            int len = result.size();// fn组合的长度
            result.add((new int[]{source[source.length - 1]}));
            for (int i = 0; i < len; i++) {
                int[] tmp = new int[result.get(i).length + 1];
                for (int j = 0; j < tmp.length - 1; j++) {
                    tmp[j] = result.get(i)[j];
                }
                tmp[tmp.length - 1] = source[source.length - 1];
                result.add(tmp);
            }
        }
        return result;
    }
}
